
/*
 * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"

#include "wifi_connect.h"
#include "lwip/sockets.h"
#include "wifiiot_errno.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_adc.h"
#include "wifiiot_uart.h"

#include "wifi_connect.h"
#include "oc_mqtt.h"
#include "oc_mqtt_profile_package.h"

//#define UART_TASK_STACK_SIZE 1024 * 8
#define UART_TASK_PRIO 25
#define UART_BUFF_SIZE 100
#define MSGQUEUE_OBJECTS 16 // number of Message Queue Object
unsigned char count_num = 0;
// osMutexId_t mutex_id;
typedef struct
{ // object data type
    char *Buf;
    uint8_t Idx;
} MSGQUEUE_OBJ_t;

MSGQUEUE_OBJ_t msg;
osMessageQueueId_t mid_MsgQueue; // message queue id

#define CLIENT_ID "62cfe59e6b9813541d515f81_0000_0_0_2022071410"
#define USERNAME "62cfe59e6b9813541d515f81_0000"
#define PASSWORD "d9772c4df7425238ea32b5747123ff754e77d8af0cf7e6628c254e1d6a43d49a"
typedef enum
{
	OFF = 0,
	ON
} k_Status_ENUM;
typedef enum
{
    en_msg_cmd = 0,
    en_msg_report,
} en_msg_type_t;

typedef struct
{
    char *request_id;
    char *payload;
} cmd_t;

typedef struct
{
    int mask_num;
    int no_mask_num;
    int device_number;
    int total;

} report_t;

typedef struct
{
    en_msg_type_t msg_type;
    union
    {
        cmd_t cmd;
        report_t report;
    } msg;
} app_msg_t;

typedef struct
{
    int connected;
    int Status;
} app_cb_t;
static app_cb_t g_app_cb;

void Conter_IO_INIT(void)
{
        //初始化GPIO
    GpioInit();

    //设置GPIO_2的复用功能为普通GPIO
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10,WIFI_IOT_IO_FUNC_GPIO_10_GPIO);

    //设置GPIO_2为输出模式
    GpioSetDir(WIFI_IOT_GPIO_IDX_10, WIFI_IOT_GPIO_DIR_OUT);

    //GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 1);
}

void K210_StatusSet(k_Status_ENUM status)
{
    if (status == ON)

        //设置GPIO_2输出高电平点K210开始工作
        GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 1);
    if (status == OFF)

        //设置GPIO_2输出低电平关闭灯
        GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 0);
}

static void deal_report_msg(report_t *report)
{
    oc_mqtt_profile_service_t service;
    oc_mqtt_profile_kv_t Monitor;
    oc_mqtt_profile_kv_t device_number;
    oc_mqtt_profile_kv_t no_mask_num;
    oc_mqtt_profile_kv_t mask_num;
    oc_mqtt_profile_kv_t total;
    oc_mqtt_profile_kv_t detection;

    service.event_time = NULL;
    service.service_id = "Monitor";
    service.service_property = &device_number;
    service.nxt = NULL;

    device_number.key = "device_number";
    device_number.value = &report->device_number;
    device_number.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    device_number.nxt = &no_mask_num;

    no_mask_num.key = "no_mask_num";
    no_mask_num.value = &report->no_mask_num;
    no_mask_num.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    no_mask_num.nxt = &mask_num;

    mask_num.key = "mask_num";
    mask_num.value = &report->mask_num;
    mask_num.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    mask_num.nxt = &total;

    total.key = "total";
    total.value = &report->total;
    total.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    total.nxt = &detection;
    

    detection.key = "K210_Status";
    detection.value = g_app_cb.Status ? "ON" : "OFF";
    detection.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    detection.nxt = NULL;

    oc_mqtt_profile_propertyreport(USERNAME, &service);
    return;
}

void oc_cmd_rsp_cb(uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size)
{
    app_msg_t *app_msg;

    int ret = 0;
    app_msg = malloc(sizeof(app_msg_t));
    app_msg->msg_type = en_msg_cmd;
    app_msg->msg.cmd.payload = (char *)recv_data;

    printf("recv data is %.*s\n", recv_size, recv_data);
    ret = osMessageQueuePut(mid_MsgQueue, &app_msg, 0U, 0U);
    if (ret != 0)
    {
        free(recv_data);
    }
    *resp_data = NULL;
    *resp_size = 0;
}

///< COMMAND DEAL
#include <cJSON.h>
static void deal_cmd_msg(cmd_t *cmd)
{
    cJSON *obj_root;
    cJSON *obj_cmdname;
    cJSON *obj_paras;
    cJSON *obj_para;

    int cmdret = 1;
    oc_mqtt_profile_cmdresp_t cmdresp;
    obj_root = cJSON_Parse(cmd->payload);
    if (NULL == obj_root)
    {
        goto EXIT_JSONPARSE;
    }

    obj_cmdname = cJSON_GetObjectItem(obj_root, "command_name");
    if (NULL == obj_cmdname)
    {
        goto EXIT_CMDOBJ;
    }
    if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "Mask_detection_control"))
    {
        obj_paras = cJSON_GetObjectItem(obj_root, "paras");
        if (NULL == obj_paras)
        {
            goto EXIT_OBJPARAS;
        }
        obj_para = cJSON_GetObjectItem(obj_paras, "switch");
        if (NULL == obj_para)
        {
            goto EXIT_OBJPARA;
        }
        ///< operate the LED here
        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            g_app_cb.Status = 1;
            K210_StatusSet(ON);
            printf("K210 On!");
        }
        else
        {
            g_app_cb.Status = 0;
            K210_StatusSet(OFF);
            printf("K210 Off!");
        }
        cmdret = 0;
    }


EXIT_OBJPARA:
EXIT_OBJPARAS:
EXIT_CMDOBJ:
    cJSON_Delete(obj_root);
EXIT_JSONPARSE:
    ///< do the response
    cmdresp.paras = NULL;
    cmdresp.request_id = cmd->request_id;
    cmdresp.ret_code = cmdret;
    cmdresp.ret_name = NULL;
    (void)oc_mqtt_profile_cmdresp(NULL, &cmdresp);
    return;
}

static int task_main_entry(void)
{
    app_msg_t *app_msg;

    uint32_t ret = WifiConnect("HUAWEI-0400HH", "asdplm188963.");
    device_info_init(CLIENT_ID, USERNAME, PASSWORD);
    oc_mqtt_init();
    oc_set_cmd_rsp_cb(oc_cmd_rsp_cb);

    while (1)
    {
        // osMutexAcquire(mutex_id, osWaitForever);
        app_msg = NULL;
        (void)osMessageQueueGet(mid_MsgQueue, (void **)&app_msg, NULL, 0U);
        if (NULL != app_msg)
        {
            switch (app_msg->msg_type)
            {
            case en_msg_cmd:
                deal_cmd_msg(&app_msg->msg.cmd);
                break;
            case en_msg_report:
                deal_report_msg(&app_msg->msg.report);
                break;
            default:
                break;
            }
            free(app_msg);
        }
        // osMutexRelease(mutex_id);
        // osDelay(100U);
    }
    return 0;
}


static int task_uart_entry(void)
{
    app_msg_t *app_msg;
    unsigned char uart_buff[UART_BUFF_SIZE] = {0},mid_num[10] = {0};
    unsigned char *uart_buff_ptr = uart_buff;
    unsigned char  mask_flag = 0,read_temp = 0;
    unsigned char  step = 0,no_mask_num = 0,mask_num = 0;
    uint32_t ret,temp_num = 0,end_num= 0;
    uint32_t mid_temp_a = 0,temp_num_a = 0;
    unsigned char j = 0;
    Conter_IO_INIT();
    WifiIotUartAttribute uart_attr = {

        //baud_rate: 9600
        .baudRate = 2400,
        //data_bits: 8bits
        .dataBits = 8,
        .stopBits = 1,
        .parity = 0,
    };

    //Initialize uart driver
    ret = UartInit(WIFI_IOT_UART_IDX_1, &uart_attr, NULL);
    if(ret != WIFI_IOT_SUCCESS)
    {
        printf("Failed to init uart! Err code = %d\n", ret);
       
    }
    while (1)
    {  
        //  osMutexAcquire(mutex_id, osWaitForever);
        app_msg = malloc(sizeof(app_msg_t));
        printf("=======================================\r\n");
        printf("*************UART_READ_TO_K210**************\r\n");
        printf("=======================================\r\n");
        //通过串口1接收数据
        UartRead(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE);
        for(uint8_t i = 0;i < UART_BUFF_SIZE;i++)
        {
            if((*(uart_buff_ptr+i)) != '\n' )
            {
                read_temp =(*(uart_buff_ptr+i));
                printf("read_temp:%d\r",read_temp);
                switch(step)
                {
                case 0:
                     step = 0;
                    if(read_temp == 65 )
                    {
                        step  = 1;
                    }
                    if(read_temp == 69)
                    {
                         step  = 1;
                         mask_flag = 1;
                    }
                    break;
                case 1:
                    step = 0;
                    if(read_temp == 65 )
                    {
                        step  = 2;
                    }
                    if(read_temp == 69)
                    {
                        step  = 2;
                    }
                    break;
                case 2:
                    mid_num[count_num] = read_temp;
                    count_num = count_num +1;
                    printf("count_num:%d\r\n",count_num);
                    break;
                default:
                    break;
                }
            }
            else
            {
                step = 0;
                break;
            }
        }

        if (count_num == 1)
         {
            count_num = 0;
            end_num =  (mid_num[0]-48);
        }
        if(count_num>1)
        {
            j = count_num-1;
            for (uint8_t i = 0; i< count_num ; i++)
            {
                mid_temp_a = mid_num[i] - 48;
                temp_num_a = pow(10,j)*mid_temp_a+temp_num_a;
                j--;
            }
            j=0;
            count_num = 0;
            end_num= temp_num_a; 
            mid_temp_a = 0;
            temp_num_a = 0;
        }
        //usleep(5);
        // UartWrite(WIFI_IOT_UART_IDX_1, (unsigned char *)uart_buff_ptr,3);
        printf("end_num:%d\r\n",end_num);
        if(mask_flag != 0) {mask_num = end_num ; mask_flag = 0;} else no_mask_num = end_num;
        //no_mask_num = end_num;
        if (NULL != app_msg)
        {  
            app_msg->msg_type = en_msg_report; 
            app_msg->msg.report.device_number = 001 ;
            app_msg->msg.report.mask_num = mask_num ;
            app_msg->msg.report.no_mask_num = no_mask_num ;
            app_msg->msg.report.total = (no_mask_num+mask_num) ;

            if (0 != osMessageQueuePut(mid_MsgQueue, &app_msg, 0U, 0U))//发送消息
            {
                free(app_msg);
            }
        }
        // osMutexRelease(mutex_id);
        sleep(5);
    }
    return 0;
} 

static void OC_init(void)
{
    
    mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, 10, NULL);//创建一个消息队列
    if (mid_MsgQueue == NULL)
    {
        printf("Falied to create Message Queue!\n");
    }

    osThreadAttr_t attr;

    attr.name = "task_main_entry";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = 24;

    if (osThreadNew((osThreadFunc_t)task_main_entry, NULL, &attr) == NULL)
    {
        printf("Falied to create task_main_entry!\n");
    }
    attr.stack_size = 1024*8;
    attr.priority = 25;
    attr.name = "task_uart_entry";
    if (osThreadNew((osThreadFunc_t)task_uart_entry, NULL, &attr) == NULL)
    {
        printf("Falied to create task_uart_entry!\n");
    }
    // mutex_id = osMutexNew(NULL);
    // if (mutex_id == NULL)
    // {
    // printf("Falied to create Mutex!\n");
    // }

}

APP_FEATURE_INIT(OC_init);